package net.simflow.swf.analyzer.stringtrans;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.TreeSet;

import net.simflow.swf.analyzer.bgnetwork.data.BGNode;
import net.simflow.swf.analyzer.bgnetwork.stats.data.BGNetworkStats;
import net.simflow.swf.analyzer.data.StringConstant;
import net.simflow.swf.analyzer.data.TupleStrInt;

public class BGNetworkStatsStringGenerator {
	private static final int MAX_LENGTH = 10;

	private static BGNetworkStatsStringGenerator instance = new BGNetworkStatsStringGenerator();

	private BGNetworkStatsStringGenerator() {
	}

	public static BGNetworkStatsStringGenerator getInstance() {
		return instance;
	}

	public ArrayList<TupleStrInt> generate(String style, BGNetworkStats nstats) {
		switch (style) {
		case BGNetworkStats.NETWORK_NAME:
			return this.getNameString(style, nstats.getNetworkName());
		case BGNetworkStats.NETWORK_FLOW_NEIGHBOR:
			return this.getNeighborString(style,
					nstats.getNetworkFlowNeighborMap());
		case BGNetworkStats.NETWORK_SERVICE_NEIGHBOR:
			return this.getNeighborString(style,
					nstats.getNetworkServiceNeighborMap());
		case BGNetworkStats.NETWORK_FLOW_DEGREE:
			return this.getDegreeDistributionString(style,
					nstats.getNetworkFlowDegreeDistribution());
		case BGNetworkStats.NETWORK_SERVICE_DEGREE:
			return this.getDegreeDistributionString(style,
					nstats.getNetworkServiceDegreeDistribution());
		case BGNetworkStats.FLOW_PART_NAME:
			return this.getNameString(style, nstats.getFlowNetworkName());
		case BGNetworkStats.FLOW_PART_NEIGHBOR:
			return this.getNeighborString(style, nstats.getFlowNeighborMap());
		case BGNetworkStats.FLOW_PART_DEGREE:
			return this.getDegreeDistributionString(style,
					nstats.getFlowNetworkDegreeDistribution());
		case BGNetworkStats.SERVICE_PART_NAME:
			return this.getNameString(style, nstats.getServiceNetworkName());
		case BGNetworkStats.SERVICE_PART_NEIGHBOR:
			return this
					.getNeighborString(style, nstats.getServiceNeighborMap());
		case BGNetworkStats.SERVICE_PART_DEGREE:
			return this.getDegreeDistributionString(style,
					nstats.getServiceNetworkDegreeDistribution());
		}
		return null;
	}

	private ArrayList<TupleStrInt> getNameString(String title, String name) {
		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();
		info.add(new TupleStrInt(title, StringConstant.TITLE));
		info.add(new TupleStrInt(name, StringConstant.CONTENT));
		return info;
	}

	private ArrayList<TupleStrInt> getNeighborString(String title,
			HashMap<BGNode, HashSet<BGNode>> map) {
		if (map == null) {
			return null;
		}

		TreeSet<String> set = new TreeSet<String>();
		for (Entry<BGNode, HashSet<BGNode>> en : map.entrySet()) {
			TreeSet<String> tmp = new TreeSet<String>();
			for (BGNode node : en.getValue()) {
				tmp.add(node.getNameInBG());
				if (tmp.size() >= MAX_LENGTH) {
					break;
				}
			}
			tmp.comparator();

			StringBuffer str = new StringBuffer();
			str.append(en.getKey().getNameInBG());
			str.append(" (").append(en.getValue().size()).append("): ");
			for (String s : tmp) {
				str.append(" ").append(s).append(";");
			}
			if (tmp.size() >= MAX_LENGTH && en.getValue().size() > MAX_LENGTH) {
				str.append("...");
			}

			set.add(str.toString());
		}
		set.comparator();

		if (set.isEmpty()) {
			return null;
		}

		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();
		info.add(new TupleStrInt(title, StringConstant.TITLE));
		for (String str : set) {
			info.add(new TupleStrInt(str.toString(), StringConstant.CONTENT));
		}

		return info;
	}

	private ArrayList<TupleStrInt> getDegreeDistributionString(String title,
			TreeMap<Integer, HashSet<BGNode>> map) {
		if (map == null) {
			return null;
		}
		map.comparator();

		ArrayList<TupleStrInt> info = new ArrayList<TupleStrInt>();
		for (Entry<Integer, HashSet<BGNode>> en : map.descendingMap()
				.entrySet()) {
			TreeSet<String> set = new TreeSet<String>();
			for (BGNode node : en.getValue()) {
				set.add(node.getNameInBG());
				if (set.size() >= MAX_LENGTH) {
					break;
				}
			}
			set.comparator();

			StringBuffer str = new StringBuffer();
			str.append(en.getKey());
			str.append(" (").append(en.getValue().size()).append("): ");
			for (String s : set) {
				str.append(" ").append(s).append(";");
			}
			if (set.size() >= MAX_LENGTH && en.getValue().size() > MAX_LENGTH) {
				str.append("...");
			}

			info.add(new TupleStrInt(str.toString(), StringConstant.CONTENT));
		}

		if (info.isEmpty()) {
			return null;
		}

		info.add(0, new TupleStrInt(title, StringConstant.TITLE));
		return info;
	}
}
